package korkd.tower;


import java.util.LinkedList;

import org.anddev.andengine.engine.camera.BoundCamera;
import org.anddev.andengine.engine.handler.IUpdateHandler;
import org.anddev.andengine.engine.handler.timer.ITimerCallback;
import org.anddev.andengine.engine.handler.timer.TimerHandler;
import org.anddev.andengine.entity.Entity;
import org.anddev.andengine.entity.layer.tiled.tmx.TMXTile;
import org.anddev.andengine.entity.layer.tiled.tmx.TMXTiledMap;
import org.anddev.andengine.entity.primitive.Rectangle;
import org.anddev.andengine.entity.scene.Scene;
import org.anddev.andengine.entity.sprite.Sprite;
import org.anddev.andengine.input.touch.TouchEvent;
import org.anddev.andengine.opengl.texture.region.TextureRegion;
import org.anddev.andengine.util.MathUtils;
import org.anddev.andengine.util.constants.Constants;

import android.view.MotionEvent;

class Tower extends Entity
{	
	private int mRange;
	private float mRate;
	private Tower mTower = this;
	private int mTileCount = 4;
	private Rectangle[] mTileRectangle = new Rectangle[mTileCount];
	private TMXTile[] mTowerTMXTile = new TMXTile[mTileCount];
	private boolean mValidPlacement;
	private boolean mPlaced;
	private int mHealth;
	private Sprite mTowerSprite;
	private Sprite mTowerRegion;
	private BulletPool mBulletPool;
	
	public Tower(float pX, float pY, TextureRegion pTextureRegion, TextureRegion pTowerRangeRegion, final UnitPool pUnitPool, BulletPool pBulletPool) {
		super(pX, pY);
		mRange = 250;
		mRate = 1.0f;
		mHealth = 300;
		mPlaced = false;
		mBulletPool = pBulletPool;
		this.setVisible(false);
		this.setPosition(-50,-50);
		
		mTowerRegion = new Sprite(0, 0, pTowerRangeRegion);
        mTowerSprite = new Sprite(0,0, pTextureRegion);
        
        mTowerRegion.setColor(0.1f, 0.1f, 0.1f, 0.1f);
        mTowerRegion.setPosition((-(mTowerRegion.getWidth() * 0.5f)) + mTowerSprite.getWidth() * 0.5f,0);
        mTowerRegion.setScale(1.5f);
		this.attachChild(mTowerRegion);
		this.attachChild(mTowerSprite);
		
		// Register the update handler for firing bullets
		this.registerUpdateHandler(new TimerHandler(mRate, true, new ITimerCallback(){
			@Override
			public void onTimePassed(TimerHandler pTimerHandler) {
				for(Unit u : pUnitPool.getUnitList())
				{	
					float cRange = MathUtils.distance(u.getX()+(u.getWidth()/2), 
										u.getY()+(u.getHeight()/2),
										mTower.getX()+(mTower.mTowerSprite.getWidth()/2),
										mTower.getY()+(mTower.mTowerSprite.getHeight()/2));
					
					if(cRange < mRange && u.isAlive() && mPlaced)
					{
						mTower.fire(u);
						break;
					}
				}
			}}));
	}
	
	public void fire(Unit u)
	{
		Bullet b = mBulletPool.obtainPoolItem();
		b.setPosition(this.getX()+(this.mTowerSprite.getWidth()/2), this.getY()+(this.mTowerSprite.getHeight()/2));
		b.travel(u, mBulletPool);
	}
	
	public void create(final TMXTiledMap pMap, Scene pScene, final LinkedList<TMXTile> pUsedList)
	{
		for(int i = 0; i < mTileCount; i++)
		{
			mTileRectangle[i] = new Rectangle(0,0,pMap.getTileWidth(), pMap.getTileHeight());
			mTileRectangle[i].setColor(0.2f, 0.2f, 0.2f, 0.4f);
			mTileRectangle[i].setVisible(false);
			pScene.attachChild(mTileRectangle[i]);
		}

        this.registerUpdateHandler(new IUpdateHandler() 
        {

			@Override
            public void reset() { }

            @Override
            public void onUpdate(final float pSecondsElapsed) 
            {

                final float[] TowerCoords = mTower.convertLocalToSceneCoordinates(0 ,mTower.mTowerSprite.getHeight());
                
                //TowerCoords[Constants.VERTEX_INDEX_X] += mTower.getWidth() * 0.5f;
                TowerCoords[Constants.VERTEX_INDEX_Y] += mTower.mTowerSprite.getHeight() * 0.1f;
                
                mTowerTMXTile[0] = pMap.getTMXLayers().get(0).getTMXTileAt(TowerCoords[Constants.VERTEX_INDEX_X], TowerCoords[Constants.VERTEX_INDEX_Y]);
                mTowerTMXTile[1] = pMap.getTMXLayers().get(0).getTMXTileAt(TowerCoords[Constants.VERTEX_INDEX_X]+40, TowerCoords[Constants.VERTEX_INDEX_Y]);
                mTowerTMXTile[2] = pMap.getTMXLayers().get(0).getTMXTileAt(TowerCoords[Constants.VERTEX_INDEX_X], TowerCoords[Constants.VERTEX_INDEX_Y]-40);
                mTowerTMXTile[3] = pMap.getTMXLayers().get(0).getTMXTileAt(TowerCoords[Constants.VERTEX_INDEX_X]+40, TowerCoords[Constants.VERTEX_INDEX_Y]-40);

                mValidPlacement = true;
                
                for(int i = 0; i < mTileCount; i++)
                {
                    if(mTowerTMXTile[i] != null) 
                    {
                    	if(Integer.parseInt(mTowerTMXTile[i].getTMXTileProperties(pMap).get(0).getValue()) != 100
                    			|| pUsedList.contains(mTowerTMXTile[i]))
                    	{
                    		mTileRectangle[i].setColor(1, 0, 0);
                    		mValidPlacement = false;
                    	}
                    	else
                    	{
                    		mTileRectangle[i].setColor(0.2f, 0.2f, 0.2f);
                    	}
                            // tmxTile.setTextureRegion(null); <-- Rubber-style removing of tiles =D
                    	mTileRectangle[i].setPosition(mTowerTMXTile[i].getTileX(), mTowerTMXTile[i].getTileY());
                    }
                }
        	}
        });
        
        pScene.attachChild(this);
	}
	
	public boolean place(TouchEvent pTouchEvent, BoundCamera pBoundCamera, LinkedList<TMXTile> pUsedTiles)
	{
		boolean remove = false;
		
		float X = pBoundCamera.getMinX() + pTouchEvent.getMotionEvent().getX();
        float Y = pBoundCamera.getMinY() + pTouchEvent.getMotionEvent().getY();
        int i = 0;
        
        X -= X % 40;
        Y -= Y % 40;
        
        X -= this.mTowerSprite.getWidth() * 0.5f;
        Y -= this.mTowerSprite.getHeight() * 0.9f;
        
        this.setVisible(true);
        
        for(i = 0; i < this.mTileCount; i++)
        {
        	this.mTileRectangle[i].setVisible(true);
        }
        
        this.setPosition(X, Y);
		
		if(pTouchEvent.getAction() == MotionEvent.ACTION_UP)
        {
			mTowerRegion.setVisible(false);
			
			for(i = 0; i < this.mTileCount; i++)
            {
				this.mTileRectangle[i].setVisible(false);
            }
			
			if(this.mValidPlacement)
			{
				mPlaced = true;
				for(i = 0; i < this.mTileCount; i++)
                {
					pUsedTiles.add(this.mTowerTMXTile[i]);
                }
			}
			else
			{
				mPlaced = false;
				remove = true;
				this.setVisible(false);
				this.clearUpdateHandlers();
				this.reset();
			}
        }
		
		return remove;
	}

	public Rectangle getTileRect(int index)
	{
		return mTileRectangle[index];
	}
	
	public TMXTile getTile(int index)
	{
		return mTowerTMXTile[index];
	}
	
	public int getTileCount()
	{
		return mTileCount;
	}

	public boolean getValidPlacement()
	{
		return mValidPlacement;
	}

	public int getHealth() {
		return mHealth;
	}

	public void setHealth(int mHealth) {
		this.mHealth = mHealth;
	}
		
}